package cn.crap.schedule;

import cn.crap.enumeration.MonitorType;
import cn.crap.inter.service.table.IInterfaceService;
import cn.crap.inter.service.tool.ICacheService;
import cn.crap.inter.service.tool.IEmailService;
import cn.crap.model.Interface;
import cn.crap.springbeans.Config;
import cn.crap.utils.Const;
import cn.crap.utils.HttpPostGet;
import cn.crap.utils.MyString;
import cn.crap.utils.Tools;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class InterfaceMonitor implements Task {
    @Autowired
    private ICacheService cacheService;
    @Autowired
    private IInterfaceService interfaceService;
    @Autowired
    private IEmailService emailService;

    private int time = 0;// 接口读取缓存实际
    private int tryTimes = 0;
    private int emailSendIndex = 2;// 邮件发送指数
    private Executor exec;
    private String errorTemplet = "第%s次：返回数据有误，result=%s<br/>";

    @Autowired
    public void setExecutor(Config config) {
        if (exec == null) {
            exec = Executors.newFixedThreadPool(config.getCacheTime());
            time = config.getMonitorCacheTime();
            tryTimes = config.getMonitorTryTimes();
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void doTask() {
        try {
            List<Interface> interfaces = null;
            if (time > 0) {
                interfaces = (List<Interface>) cacheService.getObj(Const.CACHE_MONITOR_INTERFACES);
            }

            if (interfaces == null) {
                interfaces = interfaceService.findByMap(Tools.getMap("monitorType|>", 0), null, null);
                if (time > 0) {
                    cacheService.setObj(Const.CACHE_MONITOR_INTERFACES, interfaces, time);
                }
            }
            for (Interface inter : interfaces) {
                task(inter);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void task(final Interface inter) {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                inter.getMonitorType();
                String method = ("," + inter.getMethod());
                String result = "";
                int myTryTimes = 0;
                int errorTimes = 0;
                StringBuilder errorMesg = new StringBuilder();
                while (myTryTimes < tryTimes) {
                    myTryTimes++;
                    try {
                        if (method.contains(",POST,") && !inter.getParam().startsWith("form=")) {
                            result = HttpPostGet.postBody(inter.getFullUrl(), inter.getParam(), getMapFromStr(inter.getHeader()));
                        } else if (method.contains(",POST,")) {
                            result = HttpPostGet.post(inter.getFullUrl(), getMapFromStr(inter.getParam().substring(5)), getMapFromStr(inter.getHeader()));
                        } else if (method.contains(",GET,")) {
                            result = HttpPostGet.post(inter.getFullUrl(), getMapFromStr(inter.getParam().substring(5)), getMapFromStr(inter.getHeader()));
                        } else if (method.contains(",PUT,")) {
                            result = HttpPostGet.post(inter.getFullUrl(), getMapFromStr(inter.getParam().substring(5)), getMapFromStr(inter.getHeader()));
                        } else if (method.contains(",DELETE,")) {
                            result = HttpPostGet.post(inter.getFullUrl(), getMapFromStr(inter.getParam().substring(5)), getMapFromStr(inter.getHeader()));
                        } else if (method.contains(",HEAD,")) {
                            result = HttpPostGet.post(inter.getFullUrl(), getMapFromStr(inter.getParam().substring(5)), getMapFromStr(inter.getHeader()));
                        } else if (method.contains(",OPTIONS,")) {
                            result = HttpPostGet.post(inter.getFullUrl(), getMapFromStr(inter.getParam().substring(5)), getMapFromStr(inter.getHeader()));
                        } else if (method.contains(",TRACE,")) {
                            result = HttpPostGet.post(inter.getFullUrl(), getMapFromStr(inter.getParam().substring(5)), getMapFromStr(inter.getHeader()));
                        }
                    } catch (Exception e) {
                        // 网络异常
                        errorTimes++;
                        errorMesg.append("第" + myTryTimes + "次：网络异常，" + e.getMessage() + "<br/>");
                        continue;
                    }

                    if (inter.getMonitorType() == MonitorType.NetworkInclude.getValue()) {
                        if (result.contains(inter.getMonitorText().trim())) {
                            errorTimes++;
                            errorMesg.append(String.format(errorTemplet, myTryTimes + "", StringEscapeUtils.escapeHtml(result)));
                            continue;
                        }
                    }

                    if (inter.getMonitorType() == MonitorType.NetworkNotInclude.getValue()) {
                        if (!result.contains(inter.getMonitorText().trim())) {
                            errorTimes++;
                            errorMesg.append(String.format(errorTemplet, myTryTimes + "", StringEscapeUtils.escapeHtml(result)));
                            continue;
                        }
                    }

                    if (inter.getMonitorType() == MonitorType.NetworkNotEqual.getValue()) {
                        if (inter.getMonitorText().trim().equals(result.trim())) {
                            errorTimes++;
                            errorMesg.append(String.format(errorTemplet, myTryTimes + "", StringEscapeUtils.escapeHtml(result)));
                            continue;
                        }
                    }

                    if (inter.getMonitorType() == MonitorType.NetworkEqual.getValue()) {
                        if (!inter.getMonitorText().trim().equals(result.trim())) {
                            errorTimes++;
                            errorMesg.append(String.format(errorTemplet, myTryTimes + "", StringEscapeUtils.escapeHtml(result)));
                            continue;
                        }
                    }
                    break;
                }
                if (errorTimes > 0 && !MyString.isEmpty(inter.getMonitorEmails())) {
                    int hasSendTimes = 1;
                    if (cacheService.getStr(Const.CACHE_MONITOR_INTERFACES_HAS_SEND_EMAIL + inter.getId()) == null) {
                        String hasSendTimesStr = cacheService.getStr(Const.CACHE_MONITOR_INTERFACES_EMAIL_TIMES + inter.getId());
                        if (hasSendTimesStr != null) {
                            hasSendTimes = Integer.parseInt(hasSendTimesStr) + 1;
                        }
                        // 一天内有效
                        cacheService.setStr(Const.CACHE_MONITOR_INTERFACES_EMAIL_TIMES + inter.getId(), hasSendTimes + "", 3 * 60 * 60);
                        cacheService.setStr(Const.CACHE_MONITOR_INTERFACES_HAS_SEND_EMAIL + inter.getId(), "1", (int) Math.pow(emailSendIndex, hasSendTimes));

                        for (String email : inter.getMonitorEmails().split(";")) {
                            emailService.sendMail("接口监控：" + inter.getInterfaceName(), email, "尝试：" + myTryTimes + "次，失败：" + errorTimes + "次<br/>" + errorMesg.toString());
                        }
                    }
                }
            }
        };
        exec.execute(task);
    }

    private Map<String, String> getMapFromStr(String str) {
        JSONArray jsonStr = JSONArray.parseArray(str);
        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < jsonStr.size(); i++) {
            JSONObject json = jsonStr.getJSONObject(i);
            map.put(json.getString("name"), json.getString("def"));
        }
        return map;
    }
}